#pragma once
#include "yzrutil.h"
#include "lang/Math.h"
#include <cmath>
#include <array>
#include <type_traits>
namespace yzrilyzr_dsp{
	template<u_index TableSize=4096, bool UseInterpolation=true>
	EBCLASS(FastSin){
	private:
	static_assert((TableSize & (TableSize - 1)) == 0, "TableSize must be power of 2");

	static constexpr u_sample TABLE_SIZE_D=static_cast<u_sample>(TableSize);
	static constexpr u_sample INV_TABLE_SIZE=1.0 / TABLE_SIZE_D;
	static constexpr u_sample PHASE_SCALE=TABLE_SIZE_D / yzrilyzr_lang::Math::TAU;
	static constexpr u_index TABLE_MASK=TableSize - 1;

	std::array<u_sample, TableSize> lut;

	// 快速模运算（对于2的幂次表大小）
	u_index fast_mod(u_index index) const{
		return index & TABLE_MASK;
	}

	public:
	FastSin() : lut(){
		for(u_index i=0; i < TableSize; ++i){
			u_sample phase=(static_cast<u_sample>(i) * INV_TABLE_SIZE) * yzrilyzr_lang::Math::TAU;
			lut[i]=std::sin(phase);
		}
	}

	// 主sin函数
	u_sample operator()(u_sample x) const{
		// 规范化相位
		x=std::fmod(x, yzrilyzr_lang::Math::TAU);
		if(x < 0) x+=yzrilyzr_lang::Math::TAU;

		if constexpr(UseInterpolation){
			// 带插值的版本
			u_sample position=x * PHASE_SCALE;
			u_index index0=static_cast<u_index>(position);
			u_sample fraction=position - index0;

			u_index index1=fast_mod(index0 + 1);
			index0=fast_mod(index0);

			return lut[index0] * (1.0 - fraction) + lut[index1] * fraction;
		} else{
			// 不带插值的版本（更快但精度较低）
			u_index index=static_cast<u_index>(x * PHASE_SCALE) & TABLE_MASK;
			return lut[index];
		}
	}
	};
	inline u_sample fast_sin(u_sample x, u_sample freq){
		static FastSin<65536, false> fast_sin1;
		static FastSin<16384, false> fast_sin2;
		static FastSin<4096, false> fast_sin3;
		if(freq > 5000)return fast_sin3(x);
		if(freq > 500)return fast_sin2(x);
		return fast_sin1(x);
	}
	inline u_sample fast_cos(u_sample x, u_sample freq){
		return fast_sin(x + yzrilyzr_lang::Math::PIDIV2, freq);
	}
}
